package cascade.components
{
	import caurina.transitions.Tweener;
	
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.geom.Rectangle;
	
	import flight.html.RichText;
	
	import mx.controls.HTML;
	import mx.core.ClassFactory;
	import mx.core.EdgeMetrics;
	import mx.events.FlexEvent;
	import mx.events.ScrollEvent;

	public class CustomHTML extends HTML
	{
		protected var richText:RichText;
		private var _scrollLock:Boolean = false;
		protected var scrollLockData:Object;
		protected var editing:Boolean;
		protected var contentShadow:Sprite;
		protected var loadedContents:Array;
		
		public function CustomHTML()
		{
			addEventListener(FlexEvent.CREATION_COMPLETE, onCreated);
			htmlLoaderFactory = new ClassFactory(RichText);
		}
		
		protected override function createChildren():void
		{
			super.createChildren();
			richText = htmlLoader as RichText;
		}
		
		private function onCreated(event:FlexEvent):void
		{
			addEventListener(ScrollEvent.SCROLL, onScroll);
			htmlLoader.addEventListener(Event.SCROLL, onScroll);
			htmlLoader.addEventListener(Event.COMPLETE, onPageLoad);
			addEventListener(Event.LOCATION_CHANGE, onLocationChange);
		}
		
		private function onLocationChange(event:Event):void
		{
			event.preventDefault();
		}
		
		protected function onPageLoad(event:Event):void
		{
			loadedContents = getContents();
		}
		
		private function onScroll(event:Event):void
		{
			invalidateDisplayList();
		}
		
		public function get scrollLock():Boolean
		{
			return _scrollLock;
		}
		
		public function set scrollLock(value:Boolean):void
		{
			_scrollLock = value;
			if (value)
				scrollLockData = {pos: htmlLoader.scrollV, height: height};
		}
		
		public override function setActualSize(w:Number, h:Number):void
		{
			scrollAreaChanged
			if (scrollLock)
				htmlLoader.scrollV = scrollLockData.pos + (scrollLockData.height - h);
			super.setActualSize(w, h);
			invalidateSize();
		}
		
		protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			if (false && editing)
			{
				var body:Object = htmlLoader.window.document.body;
				
				var x:Number = htmlLoader.scrollH;
				var y:Number = htmlLoader.scrollV;
				
				var htmlWidth:Number = htmlLoader.contentWidth;
				var htmlHeight:Number = htmlLoader.contentHeight;
				
				var em:EdgeMetrics = viewMetrics;
				contentShadow.x = em.left;
				contentShadow.y = em.top;
				
				contentShadow.scrollRect = new Rectangle(0, 0, unscaledWidth - em.right, unscaledHeight - em.bottom);
				
				var shape:Shape = contentShadow.getChildAt(0) as Shape;
				shape.x = -x;
				shape.y = -y;
				
				var g:Graphics = shape.graphics;
				var cutouts:Array = getContentRects();
				g.clear();
				g.beginFill(0);
				g.drawRect(-10, -10, htmlWidth + 20, htmlHeight + 20);
				for each (var rect:Rectangle in cutouts)
				{
					g.drawRoundRect(rect.x, rect.y, rect.width, rect.height, 8, 8);
				}
			}
		}
		
		[Bindable]
		public function get editHighlight():Boolean
		{
			return editing;
		}
		
		public function set editHighlight(value:Boolean):void
		{
			editing = value;
			if (editing)
			{
				contentShadow = new Sprite();
				contentShadow.mouseEnabled = false;
				var d:DisplayObject = contentShadow.addChild(new Shape());
				d.filters = [new BlurFilter()];
				contentShadow.alpha = 0;
				Tweener.addTween(contentShadow, {alpha: .5, delay: .5, time: 1, transition:"easeoutquad"});
				addChild(contentShadow);
			}
			else if (contentShadow)
			{
				removeChild(contentShadow);
				contentShadow = null;
			}
			
		}
		
		public function getContents():Array
		{
			
			var doc:Object = htmlLoader.window.document;
			var elems:Object = doc.getElementsByTagName("cms");
			var contents:Array = [];
			
			for (var i:uint = 0; i < elems.length; i++)
			{
				var cms:Object = elems[i];
				var name:String = cms.getAttribute("name");
				contents[name] = contents[i] = {name: name, value: richText.getHTML(cms)};
			}
			
			return contents;
		}
		
		public function getChangedContents():Array
		{
			var contents:Array = getContents();
			var changed:Array = [];
			
			var max:Number = contents.length;
			for (var i:Number = 0; i < max; i++)
			{
				var content:Object = contents[i];
				if (content.value != loadedContents[content.name].value)
					changed.push(content);
			}
			
			return changed;
		}
		
		public function resetChanges():void
		{
			var doc:Object = htmlLoader.window.document;
			var elems:Object = doc.getElementsByTagName("cms");
			
			var max:Number = elems.length;
			for (var i:uint = 0; i < max; i++)
			{
				var cms:Object = elems[i];
				var name:String = cms.getAttribute("name");
				cms.innerHTML = loadedContents[name].value;
			}
		}
		
		protected function getContentRects():Array
		{
			var doc:Object = htmlLoader.window.document;
			var elems:Object = doc.getElementsByTagName("cms");
			var editAreas:Array = [];
			
			for (var i:uint = 0; i < elems.length; i++)
			{
				var node:Object = elems[i].parentNode;
				var rect:Rectangle = new Rectangle(node.offsetLeft, node.offsetTop, node.offsetWidth, node.offsetHeight);
				while (node.offsetParent)
				{
					node = node.offsetParent;
					rect.x += node.offsetLeft;
					rect.y += node.offsetTop;
				}
				editAreas.push(rect);
			}
			
			return editAreas;
		}
	}
}